package edu.nju.mutest.mutator;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.expr.*;
import edu.nju.mutest.util.CollectorUtil;
import edu.nju.mutest.visitor.collector.BasicTypeExpressionCollector;
import edu.nju.mutest.visitor.collector.cond.BooleanCond;
import edu.nju.mutest.visitor.collector.cond.IntegerCond;
import edu.nju.mutest.visitor.collector.cond.NumericCond;
import edu.nju.mutest.visitor.collector.cond.VariableCond;

import java.util.List;

public class UnaryOperatorInsertionMutator extends AbstractMutator{

    public UnaryOperatorInsertionMutator(CompilationUnit cu) {
        super(cu);
    }

    @Override
    public List<CompilationUnit> mutate() {
        if (mutPoints == null) {
            mutPoints = CollectorUtil.collect(new BasicTypeExpressionCollector(), this.origCU);
        }

        for (Expression mp : mutPoints) {
            if (new IntegerCond().willCollect(mp)) {
                replaceNode(mp, new UnaryExpr(mp.clone(), UnaryExpr.Operator.BITWISE_COMPLEMENT));
            }
            if (new BooleanCond().willCollect(mp)) {
                replaceNode(mp, new UnaryExpr(mp.clone(), UnaryExpr.Operator.LOGICAL_COMPLEMENT));
            }
            if (new NumericCond().willCollect(mp)) {
                if (new VariableCond().willCollect(mp)) {
                    replaceNode(mp, new UnaryExpr(mp.clone(), UnaryExpr.Operator.PREFIX_INCREMENT));
                    replaceNode(mp, new UnaryExpr(mp.clone(), UnaryExpr.Operator.PREFIX_DECREMENT));
                    replaceNode(mp, new UnaryExpr(mp.clone(), UnaryExpr.Operator.POSTFIX_INCREMENT));
                    replaceNode(mp, new UnaryExpr(mp.clone(), UnaryExpr.Operator.POSTFIX_DECREMENT));
                }
                replaceNode(mp, new UnaryExpr(new EnclosedExpr(mp.clone()), UnaryExpr.Operator.MINUS));
            }
        }
        return mutants;
    }
}
